#ifndef __MQ_HOST_HPP__
#define __MQ_HOST_HPP__

#include "mq_binding.hpp"
#include "mq_exchange.hpp"
#include "mq_message.hpp"
#include "mq_queue.hpp"

namespace mq
{
    class VirtualHost
    {
    public:
        using ptr=std::shared_ptr<VirtualHost>;
        VirtualHost(const std::string &host_name, const std::string &basedir, const std::string &dbfile)
            :_host_name(host_name)
            ,_emp(std::make_shared<ExchangeMannager>(dbfile))
            ,_mqmp(std::make_shared<MsgQueueManager>(dbfile))
            ,_bmp(std::make_shared<BindingManager>(dbfile))
            ,_mmp(std::make_shared<MessageManager>(basedir))
        {
            QueueMap qmp=_mqmp->allQueues();
            for(auto& queue:qmp)
            {
                _mmp->initQueueMessage(queue.first);
            }
        }

        /*声明交换机*/
        bool declareExchange(const std::string &ename, ExchangeType etype, bool edurable, bool eauto_delete,
                             const google::protobuf::Map<std::string,std::string> &eargs)
        {
            return _emp->declareExchange(ename,etype,edurable,eauto_delete,eargs);
        }

        /*删除交换机*/
        void deleteExchange(const std::string &ename)
        {
            //删除交换机同时，也要删除该交换机上所有的绑定信息
            _bmp->removeExchangeBindings(ename);
            return _emp->deleteExchange(ename);
        }

        /*判断交换机是否存在*/
        bool existsExchange(const std::string &ename)
        {
            return _emp->exists(ename);
        }

        /*根据交换机名称获取交换机信息*/
        Exchange::ptr selectExchange(const std::string &ename)
        {
            return _emp->selectExchange(ename);
        }

        /*声明队列*/
        bool declareQueue(const std::string &qname,
                          bool qdurable,
                          bool qexclusive,
                          bool qauto_delete,
                          const google::protobuf::Map<std::string,std::string> &qargs)
        {
            _mmp->initQueueMessage(qname);//先初始化队列消息句柄
            return _mqmp->declareQueue(qname,qdurable,qexclusive,qauto_delete,qargs);//再创建队列
        }

        /*删除队列*/
        void deleteQueue(const std::string &qname)
        {
            //1.删除队列绑定信息
            _bmp->removeMsgQueueBindings(qname);
            //2.删除队列属性信息
            _mqmp->deleteQueue(qname);
            //3.删除消息队列
            _mmp->destroyQueueMessage(qname);
            return;
        }

        /*判断队列是否存在*/
        bool existsQueue(const std::string &qname)
        {
            return _mqmp->exists(qname);
        }

        /*获取所有队列属性信息*/
        QueueMap allQueues()
        {
            return _mqmp->allQueues();
        }

        /*绑定信息*/
        bool bind(const std::string& ename,const std::string& qname,const std::string& binding_key)
        {
            //1.判断交换机是否存在
            Exchange::ptr ep=_emp->selectExchange(ename);
            if(ep.get()==nullptr)
            {
                DLOG("进行信息绑定失败,交换机%s不存在",ename.c_str());
                return false;
            }
            //2.判断队列是否存在
            MsgQueue::ptr mqp=_mqmp->selectQueue(qname);
            if(mqp.get()==nullptr)
            {
                DLOG("进行信息绑定失败,队列%s不存在",qname.c_str());
                return false;
            }
            return _bmp->bind(ename,qname,binding_key,ep->durable&&mqp->durable);
        }

        /*取消绑定*/
        void unBind(const std::string& ename,const std::string& qname)
        {
            return _bmp->unBind(ename,qname);
        }

        MsgQueueBindingMap exchangeBinding(const std::string& ename)
        {
            return _bmp->getExchangeBindings(ename);
        }

        /*判断绑定信息是否存在*/
        bool existsBinding(const std::string& ename,const std::string& qname)
        {
            return _bmp->exists(ename,qname);
        }

        /*发布消息,即将消息添加进消息队列*/
        bool basicPublish(const std::string& qname,BasicProperties* bp,const std::string& body)
        {
            MsgQueue::ptr mqp=_mqmp->selectQueue(qname);
            if(mqp.get()==nullptr)
            {
                DLOG("消息发布失败,队列%s不存在",qname.c_str());
                return false;
            }
            return _mmp->insert(qname,bp,body,mqp->durable);
        }

        /*订阅消息,即消费消息*/
        MessagePtr basicConsume(const std::string& qname)
        {
            return _mmp->front(qname);
        }

        /*确定消息*/
        bool basicAck(const std::string& qname,const std::string& msg_id)
        {
            return _mmp->ack(qname,msg_id);
        }

        /*清理虚拟机所有资源*/
        void clear()
        {
            _emp->clear();
            _mqmp->clear();
            _bmp->clear();
            _mmp->clear();
        }
    private:
        std::string _host_name;     // 虚拟机名称
        ExchangeMannager::ptr _emp; // 交换机管理句柄
        MsgQueueManager::ptr _mqmp; // 消息队列管理句柄
        BindingManager::ptr _bmp;   // 消息绑定管理句柄
        MessageManager::ptr _mmp;   // 消息管理句柄
    };
}

#endif